Skip to main content

소수 찾기

문제 설명

1부터 입력받은 숫자 n 사이에 있는 소수의 개수를 반환하는 함수, solution을 만들어 보세요.

소수는 1과 자기 자신으로만 나누어지는 수를 의미합니다.

(1은 소수가 아닙니다.)

제한사항

  • n은 2이상 1000000이하의 자연수입니다.

입출력 예

nresult
104
53

입출력 예 설명

입출력 예 #1

1부터 10 사이의 소수는 [2,3,5,7] 4개가 존재하므로 4를 반환

입출력 예 #2

1부터 5 사이의 소수는 [2,3,5] 3개가 존재하므로 3를 반환

풀이

첫 번째 풀이 (시간 초과)
def isPrime(n):
if n == 1:
return False
for i in range(2, n):
if n % i == 0:
return False

return True

def solution(n):
count = 0
for i in range(1, n + 1):
if isPrime(i):
count += 1

return count

첫 번째 시도는 2부터 n-1까지 반복문을 돌면서 한 번이라도 나누어떨어지지 않으면 소수로 판단하도록 구현했습니다.

즉, 1과 자기 자신을 제외하고 어떤 수로 나누어떨어지는지, 나누어떨어지지 않는지 판단하는 소수 판별 함수를 구현해서

시도했는데 시간 초과가 발생했습니다.

n의 최댓값이 100만인데 저 방법으로 시도하면 대충 1조 번 정도 연산하리라 추정했습니다.

1초가 넘어가면 시간 초과로 실패하는 듯 보였고 연산이 1억을 넘어가면 1초를 넘어가는 것으로 알고 있어서 저 방법으로는 안 되겠다고 판단을 내렸습니다.

문제가 좀 너무하다고 느꼈던 게, 시간제한이라도 적혀 있었으면 시간복잡도를 생각해 보고 처음부터 에라토스테네스의 체로 풀었을 텐데 기입된 게 전혀 없었다는 점입니다.

두 번째 풀이
def solution(n):
check = [False] * 1000001
count = 0
for i in range(2, n + 1):
if check[i]: continue
count += 1
for j in range(i, n + 1, i):
check[j] = True

return count

두 번째 방법은 에라토스테네스의 체를 이용하여 풀었습니다.

알고리즘 원리는 다음과 같습니다.

  • check 리스트를 만들어서 모두 False 값으로 초기화한다.
  • 값에 해당하는 check 리스트가 False라면 소수이므로 하나 카운트한다.
  • 카운트한 후에 값의 배수를 모두 True로 채워 넣는다.
  • 값에 해당하는 check 리스트가 True라면 소수가 아니므로 continue

앞으로 특정 값이 소수인지 판별만 하면 되는 문제면 첫 번째 풀이 방법으로 풀 것 같고, 특정 범위의 소수의 개수를 모두 세야 한다면 에라토스테네스의 체를 사용하여 문제를 풀 것 같습니다.